//+------------------------------------------------------------------+
//|                                                    SignalRVI.mqh |
//|                             Copyright 2000-2025, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#include <Expert/ExpertSignal.h>    // 专家顾问信号基类（提供信号生成框架）

// wizard description start（MQL5 策略向导描述，用于识别类信息与参数）
//+------------------------------------------------------------------+
//| 类功能描述                                                       |
//| Title=基于相对活力指数（Relative Vigor Index）的交易信号           |
//| Type=SignalAdvanced                                              |
//| Name=Relative Vigor Index                                        |
//| ShortName=RVI                                                    |
//| Class=CSignalRVI                                                 |
//| Page=signal_rvi                                                  |
//| Parameter=PeriodRVI,int,10,计算周期（RVI 核心计算周期）             |
//+------------------------------------------------------------------+
// wizard description end

//+------------------------------------------------------------------+
//| CSignalRVI 类：基于相对活力指数（RVI）的交易信号生成器              |
//| 核心能力：继承自 CExpertSignal，通过调用 RVI 指标（衡量价格趋势强度与活力的震荡指标）， |
//|           识别2类多空信号（主信号线趋势方向、主信号线与信号线交叉）， |
//|           支持通过“信号权重”调整不同形态的优先级，适配趋势跟踪场景       |
//| 核心逻辑：RVI 由主信号线与信号线组成，主信号线反映趋势活力，信号线为其平滑线； |
//|           通过“主信号线趋势方向”“主信号线与信号线交叉”判断趋势延续与反转 |
//| 适用场景：中长线趋势跟踪（RVI 对趋势反应较平滑，假信号少），适合股票、期货等品种， |
//|           可单独使用或与波动率指标配合过滤震荡行情                     |
//+------------------------------------------------------------------+
class CSignalRVI : public CExpertSignal
  {
protected:
   // 核心组件与参数（保护，子类可访问）
   CiRVI             m_rvi;            // RVI 指标对象（封装振荡器的计算与数据读取）
   // RVI 指标可调参数（与指标原生参数对应，默认配置平衡灵敏度与趋势过滤）
   int               m_periodRVI;      // 计算周期（RVI 核心周期，默认10，值越大信号越平滑）
   // 市场形态信号权重（0-100，值越大信号优先级越高，默认配置突出线交叉信号）
   int               m_pattern_0;      // 形态0权重：主信号线趋势符合预期方向（如多单需主信号线向上）
   int               m_pattern_1;      // 形态1权重：主信号线与信号线交叉（如主信号线从下上穿信号线→多单）

public:
   //----------------------------------------------------------------
   // 构造与析构函数
   //----------------------------------------------------------------
   /**
    * @brief 构造函数：初始化 RVI 信号生成器
    * @details 1. 初始化 RVI 指标对象及默认参数（计算周期=10）；
    *          2. 设置默认信号权重（形态0=60，形态1=100，突出交叉信号的优先级）；
    *          3. 继承父类 CExpertSignal 的信号框架初始化
    */
                     CSignalRVI(void);

   /**
    * @brief 析构函数：清理 RVI 信号生成器资源
    * @details 释放指标对象占用的内存，依赖父类析构逻辑完成信号框架资源清理
    */
                    ~CSignalRVI(void);

   //----------------------------------------------------------------
   // RVI 指标参数配置：修改核心指标参数（外部调用接口）
   //----------------------------------------------------------------
   /**
    * @brief 设置 RVI 计算周期（核心参数）
    * @param value [in] 周期值（需>0，建议8-14，值越大指标对短期波动过滤越强，趋势跟踪效果越好）
    */
   void              PeriodRVI(int value);

   //----------------------------------------------------------------
   // 信号权重配置：修改不同市场形态的信号强度（外部调用接口）
   //----------------------------------------------------------------
   /**
    * @brief 设置形态0（主信号线趋势方向）的信号权重
    * @param value [in] 权重值（0-100，建议50-70，值越大越重视趋势延续的确认信号）
    */
   void              Pattern_0(int value);

   /**
    * @brief 设置形态1（主信号线与信号线交叉）的信号权重
    * @param value [in] 权重值（0-100，建议90-100，值越大越重视趋势转折的强信号）
    */
   void              Pattern_1(int value);

   //----------------------------------------------------------------
   // 参数验证：确保指标参数与信号配置有效（信号生成前提）
   //----------------------------------------------------------------
   /**
    * @brief 验证 RVI 指标参数与信号配置的有效性
    * @return bool - 验证结果：true=所有参数有效，false=存在无效参数（如周期≤0）
    * @note 验证逻辑：
    *       1. 先调用父类 ValidationSettings() 验证信号框架基础参数（如品种、周期）；
    *       2. 额外验证 RVI 计算周期（m_periodRVI）是否>0，若无效则输出错误日志并返回false
    */
   virtual bool      ValidationSettings(void);

   //----------------------------------------------------------------
   // 指标初始化：创建并注册 RVI 指标（信号生成的前提）
   //----------------------------------------------------------------
   /**
    * @brief 初始化 RVI 指标及信号所需的数据
    * @param indicators [in] 指标集合对象（用于管理所有策略用到的指标，如 RVI、均线等）
    * @return bool - 初始化结果：true=成功（指标创建+注册到指标集合），false=失败
    * @note 调用流程：
    *       1. 先调用父类 InitIndicators() 完成基础信号框架初始化；
    *       2. 调用内部 InitRVI() 方法创建 RVI 指标，绑定当前品种、周期及计算参数；
    *       3. 若指标创建失败（如参数无效、品种不支持），返回 false 并终止信号生成
    */
   virtual bool      InitIndicators(CIndicators *indicators);

   //----------------------------------------------------------------
   // 信号判断核心方法：生成多空信号权重（策略决策依据）
   //----------------------------------------------------------------
   /**
    * @brief 判断当前市场是否满足多单（买入）开仓条件，返回信号权重
    * @return int - 多单信号权重（0-100，0=无信号，值越大信号越强烈）
    * @note 核心判断逻辑（基于 RVI 指标特性，主信号线向上为前提）：
    *       1. 形态0（趋势方向）：主信号线向上 → 返回形态0权重（趋势延续确认）；
    *       2. 形态1（线交叉）：主信号线从下上穿信号线（金叉） → 返回形态1权重（强趋势信号）；
    *       3. 信号优先级：形态1 > 形态0（交叉信号确认趋势转折，权重更高）
    */
   virtual int       LongCondition(void);

   /**
    * @brief 判断当前市场是否满足空单（卖出）开仓条件，返回信号权重
    * @return int - 空单信号权重（0-100，0=无信号，值越大信号越强烈）
    * @note 核心判断逻辑（基于 RVI 指标特性，主信号线向下为前提）：
    *       1. 形态0（趋势方向）：主信号线向下 → 返回形态0权重（趋势延续确认）；
    *       2. 形态1（线交叉）：主信号线从上下穿信号线（死叉） → 返回形态1权重（强趋势信号）；
    *       3. 信号优先级：形态1 > 形态0（交叉信号确认趋势转折，权重更高）
    */
   virtual int       ShortCondition(void);

protected:
   //----------------------------------------------------------------
   // 内部辅助方法：RVI 指标初始化（仅内部调用）
   //----------------------------------------------------------------
   /**
    * @brief 创建并初始化 RVI 指标（绑定品种、周期、参数，注册到指标集合）
    * @param indicators [in] 指标集合对象（用于管理 RVI 指标）
    * @return bool - 初始化结果：true=成功（指标创建+参数配置完成），false=失败
    * @note 内部流程：
    *       1. 检查指标集合指针有效性；
    *       2. 将 RVI 指标对象（m_rvi）添加到指标集合；
    *       3. 调用 m_rvi.Create() 绑定当前交易品种、周期及计算参数（周期）；
    *       4. 若添加或创建失败，输出错误日志并返回 false
    */
   bool              InitRVI(CIndicators *indicators);

   //----------------------------------------------------------------
   // 数据读取与状态分析：快捷获取指标数据及判断状态（保护，子类可直接调用）
   //----------------------------------------------------------------
   /**
    * @brief 获取指定索引的 RVI 主信号线值
    * @param ind [in] 索引（0=当前K线，1=前一根K线，以此类推）
    * @return double - 主信号线值（反映趋势活力，值越大趋势越强）
    */
   double            Main(int ind);

   /**
    * @brief 计算指定索引K线的主信号线差值（当前K线 - 前一根K线，反映主信号线趋势方向）
    * @param ind [in] 索引（0=当前K线，1=前一根K线，以此类推）
    * @return double - 差值（>0=主信号线向上，<0=主信号线向下，反映趋势方向）
    */
   double            DiffMain(int ind);

   /**
    * @brief 获取指定索引的 RVI 信号线值（主信号线的平滑线）
    * @param ind [in] 索引（0=当前K线，1=前一根K线，以此类推）
    * @return double - 信号线值（用于与主信号线交叉产生交易信号）
    */
   double            Signal(int ind);

   /**
    * @brief 计算指定索引K线的信号线差值（当前K线 - 前一根K线，反映信号线趋势方向）
    * @param ind [in] 索引（0=当前K线，1=前一根K线，以此类推）
    * @return double - 差值（>0=信号线向上，<0=信号线向下，辅助判断趋势强度）
    */
   double            DiffSignal(int ind);

   /**
    * @brief 计算指定索引K线的主信号线与信号线差值（反映交叉状态）
    * @param ind [in] 索引（0=当前K线，1=前一根K线，以此类推）
    * @return double - 差值（>0=主信号线在信号线上方，<0=主信号线在信号线下方，用于判断金叉/死叉）
    */
   double            DiffMainSignal(int ind);
  };
//+------------------------------------------------------------------+